<?php

/**
 * Class for viewing any HTML element within a form.
 * e.g. input, textarea, select, etc.
 *
 * @author Ian Clarence ian.clarence@gmail.com
 */
class ViewHtmlFormElement extends ViewHtmlElement {

    /**
     * The element name.
     *
     * @var string
     */
    protected $name;

    /**
     * The value passed from the element when the form is submitted:
     * not necessarily the "value" attribute: e.g. if the input is of type "checkbox".
     *
     * @var string
     */
    protected $value;

    /**
     * Boolean: is the element disabled?
     *
     * @var bool
     */
    protected $disabled;

    /**
     * The label for this element: also an element itself.
     *
     * @var ViewHtmlElement
     */
    protected $labelElement;

    /**
     * Boolean: do we display the label before the element itself (default) or after it?
     *
     * @var bool
     */
    protected $displayLabelBefore;

    /**
     * The constructor.
     *
     * @param array $fields
     */
    public function __construct(array $fields = array()) {

        $this->value = isset($fields["value"]) ? $fields["value"] : (isset($fields["def_val"]) ? $fields["def_val"] : NULL);
        $fields['required'] = isset($fields['required']) ? $fields['required'] : FALSE;
        
        parent::__construct($fields);


        if (isset($this->fields["name"])) {
            $this->setAttribute("name", $this->getName());
        }

        if (isset($this->fields["label"])) {
            $this->setLabelElement($this->getLabel());
        }

        $this->setAttribute("tabindex", "");

    }

    /**
     * Getter for the value.
     *
     * @return mixed
     */
    public function getValue() {
        return $this->value;
    }

    /**
     * Setter for the value.
     * 
     * @param mixed $value
     */
    public function setValue($value) {
        $this->value = $value;
    }

    /**
     * Making this element required.
     */
    public function setRequired() {
        $this->setRequired(TRUE);
    }

    /**
     * Enable this element.
     */
    public function enable() {
        $this->setDisabled(FALSE);
        $this->unsetAttribute("disabled");
    }

    /**
     * Disable this element.
     */
    public function disable() {
        $this->setDisabled(TRUE);
        $this->setAttribute("disabled", "disabled");
    }

    /**
     * Label for the element.
     *
     * @param string $textString
     * @param bool $displayBefore
     */
    public function setLabelElement($textString, $displayLabelBefore = TRUE) {
        $indentation = $this->getIndentation();
        $labelText = new ViewHtmlElement();
        $labelText->makeText($textString);
        $this->labelElement = new ViewHtmlElement(array("tag" => "label"));
        $this->labelElement->setAttribute("for", $this->getElementId());
        $this->labelElement->addInnerHtml($labelText);
        
        $this->labelElement = $this->labelElement->encapsulate('div', NULL, array('label', $this->getElementId()));
        // $this->labelElement->setIndent($this->indent);
        $this->displayLabelBefore = $displayLabelBefore;
    }

    /**
     * Determining whether to display label before or after the element, once the label is set.
     * 
     * @param bool $displayLabelBefore
     */
    public function setDisplayLabelBefore($displayLabelBefore = TRUE) {
        $this->displayLabelBefore = $displayLabelBefore;
    }

    /**
     * Star for required elements.
     *
     * @return ViewHtmlElement
     */
    public function setStar() {
        $star = new ViewHtmlElement();
        $star->makeText("*");
        $starDiv = new ViewHtmlElement(array(
            "tag" => "div",
            "class_array" => array("required")
        ));
        $starDiv->addInnerHtml($star);
        $starDiv->setIndent($this->indent);
        return $starDiv;
    }

    /**
     * Error div for all elements, not just required: they might need validation.
     * This will be populated using JavaScript.
     *
     * @return ViewHtmlElement
     */
    public function setErrorDiv() {
        $errorMsg = new ViewHtmlElement();
        $errorMsg->makeText(" ");
        $errorDiv = new ViewHtmlElement(array(
            "tag" => "div",
            "class_array" => array("errorText", $this->getElementId(), 'hidden')
        ));
        $errorDiv->addInnerHtml($errorMsg);
        $errorDiv->setIndent($this->indent);
        return $errorDiv;
    }

    /**
     * Rendering the entire element.
     *
     * @return string
     */
    public function view() {
        $output = "";

        /**
         * Label before element.
         */
        if ($this->labelElement instanceof ViewHtmlElement) {
            $this->labelElement->setIndent($this->indent);
            if ($this->displayLabelBefore && $this->labelElement != NULL) {
                $output .= $this->labelElement->view();
            }
        }

        /**
         * If the element is required: put a star against it.
         */
        if ($this->required) {
            $output .= $this->setStar()->view();
        }

        /**
         * Normal viewing
         */
        $output .= parent::view();

        /**
         * Label after element.
         */
        if (!$this->displayLabelBefore && $this->labelElement != NULL) {
            $output .= $this->labelElement->view();
        }

        /**
         * If the element is required: create a div in case there is an error.
         */
        if ($this->getType() != 'hidden') {
            $output .= $this->setErrorDiv()->view();
        }

        /**
         * Final text string.
         */
        return $output;

    }

}